﻿Shader "HTFW/PostEffect/BloomEffect"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    
    CGINCLUDE
        #include "UnityCG.cginc"
            
        sampler2D _MainTex;
        sampler2D _SourceTex;
        float4 _MainTex_TexelSize; //src纹理的纹理大小
        
        half4 _FilterParam; //Filter参数
        half _Intensity; //强度
            
        struct a2v
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        
        struct v2f
        {
            float4 pos : SV_POSITION;
            float2 uv : TEXCOORD0;
        };
        
        /*
        half3 PreFilter(half3 col) //预先过滤部分颜色（硬过滤）
        {
            half brightness = max(col.r, max(col.g, col.b)); //亮度
            
            half contribution = max(0, brightness - _Threshold) / max(brightness, 0.00001); //贡献
        
            return col * contribution;
        }
        */
        
        half3 PreFilter(half3 col) //预先过滤部分颜色（软过滤）
        {
            half brightness = max(col.r, max(col.g, col.b)); //亮度
            
            half soft = brightness - _FilterParam.y;
            soft = clamp(soft, 0, _FilterParam.z);
            soft = soft * soft * _FilterParam.w;
            
            half contribution = max(soft, brightness - _FilterParam.x) / max(brightness, 0.00001); //贡献
        
            return col * contribution;
        }
        
        half3 sample(float2 uv) //采样
        {
            return tex2D(_MainTex, uv).rgb;
        }
        
        half3 sample_box(float2 uv, float delta)
        {
            float4 deltaUV = _MainTex_TexelSize.xyxy * float2(-delta, delta).xxyy; //(-1, -1, 1, 1)
            half3 s = sample(uv + deltaUV.xy)
                    + sample(uv + deltaUV.xz)
                    + sample(uv + deltaUV.zx)
                    + sample(uv + deltaUV.zw);
            return s * 0.25f;
        }
        
        v2f vert_bloom(a2v input)
        {
            v2f output;
            output.pos = UnityObjectToClipPos(input.vertex);
            output.uv = input.uv;
            return output;
        }
    ENDCG
    
    SubShader
    {
        Cull Off ZTest Always ZWrite Off
        
        Pass //0
        {
            CGPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment frag_bloom
            
            half4 frag_bloom(v2f input) : SV_Target
            {
                //return tex2D(_MainTex, input.uv) * half4(1, 0, 0, 0);
                return half4(PreFilter(sample_box(input.uv, 1)), 1);
            }
            
            ENDCG
        }
        
        Pass //1
        {
            CGPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment frag_bloom
            
            half4 frag_bloom(v2f input) : SV_Target
            {
                //return tex2D(_MainTex, input.uv) * half4(1, 0, 0, 0);
                return half4(sample_box(input.uv, 1), 1);
            }
            
            ENDCG
        }
        
        Pass //2
        {
            Blend One One
        
            CGPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment frag_bloom
            
            half4 frag_bloom(v2f input) : SV_Target
            {
                //return tex2D(_MainTex, input.uv) * half4(1, 0, 0, 0);
                return half4(sample_box(input.uv, 0.5), 1);
            }
            
            ENDCG
        }
        
        Pass //3
        {
            CGPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment frag_bloom
            
            half4 frag_bloom(v2f input) : SV_Target
            {
                half4 col = tex2D(_SourceTex, input.uv);
                col.rgb += sample_box(input.uv, 0.5) * _Intensity;
                return col;
            }
            
            ENDCG
        }
        
        Pass //4
        {
            CGPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment frag_bloom
            
            half4 frag_bloom(v2f input) : SV_Target
            {
                return half4(sample_box(input.uv, 0.5) * _Intensity, 1);
            }
            
            ENDCG
        }
    }
}
